package net.kleinhenz.norabase.server;

import java.io.IOException;
import java.io.PrintWriter;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.kleinhenz.norabase.server.model.Account;
import net.kleinhenz.norabase.server.model.Battlegroup;
import net.kleinhenz.norabase.server.model.RuneEntry;
import net.kleinhenz.norabase.shared.model.Rune;

import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;

public class ExportServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doGet(req, resp);
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		String bgId = req.getParameter("bgid");
		String userId = req.getParameter("user");
		String format = req.getParameter("format");		
		
		User user = UserServiceFactory.getUserService().getCurrentUser();
		String email = null;
		if (user!=null)
			email = user.getEmail();

		if (format!=null && format.equalsIgnoreCase("html"))
			resp.setContentType("text/html");
		else 
			resp.setContentType("text/plain");
		
		if (bgId!=null)
			exportBattlegroup(email, bgId, format, resp.getWriter());
		else if (userId!=null) {
			if (userId.equalsIgnoreCase(email))
				exportCollection(email, format, resp.getWriter());
			else
				printError(resp.getWriter());
		} else
			printError(resp.getWriter());
	}

	private void printError(PrintWriter writer) {

		writer.println("You do not have permissions to read that collection or battlegroup.");
		writer.close();
	}
	
	private void exportBattlegroup(String email, String bgId, String format, PrintWriter writer) {
		
		EntityManager em = EMF.get().createEntityManager();
		Battlegroup sBG = em.find(Battlegroup.class, KeyFactory.stringToKey(bgId));

		if (sBG.getAccountId().equals(email) || sBG.isPublicBattlegroup()) {
			if ("html".equalsIgnoreCase(format)) {
				writer.println("<html><body><table border='1'>");
				writer.println("<tr><td><b>Name</b></td><td><b>Type</b></td><td><b>Expansion</b></td></tr>");
				for (RuneEntry r : sBG.getRunes()) {
					Rune rune = PoxNoraXMLReader.getRune(r.getRuneId(), r.getType());
					printRuneHTML(writer, rune, null);
				}
				writer.println("</table></body></html>");
			} else
				for (RuneEntry r : sBG.getRunes()) {
					Rune rune = PoxNoraXMLReader.getRune(r.getRuneId(), r.getType());
					printRuneCSV(writer, rune, null);
				}
		} else
			printError(writer);

		em.close();				
	}

	private void exportCollection(String email, String format, PrintWriter writer) {

		EntityManager em = EMF.get().createEntityManager();
		Account account = retrieveAccount(em, email);
		if ("html".equalsIgnoreCase(format)) {
			writer.println("<html><body><table border='1'>");
			writer.println("<tr><td><b>Name</b></td><td><b>Type</b></td><td><b>Expansion</b></td><td><b>Count</b></td></tr>");
			for (RuneEntry me : account.getRunes()) {
				Rune rune = PoxNoraXMLReader.getRune(me.getRuneId(), me.getType());
				printRuneHTML(writer, rune, me.getCount());				
			}
			writer.println("</table></body></html>");
		} else
			for (RuneEntry me : account.getRunes()) {
				Rune rune = PoxNoraXMLReader.getRune(me.getRuneId(), me.getType());
				printRuneCSV(writer, rune, me.getCount());
			}			
	}

	private void printRuneCSV(PrintWriter writer, Rune rune, Integer count) {
		writer.print(rune.getName());
		writer.print(";");
		writer.print(rune.getClass().getSimpleName());
		writer.print(";");
		writer.print(rune.getExpansion());
		if (count!=null) {
			writer.print(";");
			writer.print(count);
		}
		writer.println("");
	}

	private void printRuneHTML(PrintWriter writer, Rune rune, Integer count) {
		writer.print("<tr>");
		writer.print("<td>");
		writer.print(rune.getName());
		writer.print("</td>");
		writer.print("<td>");
		writer.print(rune.getClass().getSimpleName());
		writer.print("</td>");
		writer.print("<td>");
		writer.print(rune.getExpansion());
		writer.print("</td>");
		if (count!=null) {
			writer.print("<td>");
			writer.print(count);
			writer.print("</td>");
		}
		writer.println("</tr>");
	}	

	private Account retrieveAccount(EntityManager em, String email) {

		Query q = em.createQuery("select from " + net.kleinhenz.norabase.server.model.Account.class.getName() + " where email=:email");
		q.setParameter("email", email);

		Object o = q.getSingleResult();
		if (o!=null)
			return (Account)o;
		else
			// can not happen, accounts are created on login implicitly
			throw new RuntimeException("Account not found: " + email);
	}
}
